import 'dart:collection';

import 'package:flutter/material.dart';
import 'package:flutter_demo/pages/page_with_title.dart';
import 'package:flutter_demo/widgets/app_widgets.dart';

import '../../../conf/m3.dart';

class ListenerPage extends PageWithTitle {
  ListenerPage()
      : super("监听组件(Listener)", key: GlobalKey<PageWithTitleState>());

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    return [
      const PrimaryTitle("简介"),
      const BodyText("Flutter中监听事件也是通过独立组件实现，在子组件所在区域响应事件"),
      AppSpacer.large,
      _Example(key as GlobalKey<PageWithTitleState>),
      AppSpacer.mini,
      const UlItem("Listener"),
      const BodyText("监听组件用于监听设备的触摸输入"),
      const LabelText("- onPointerDown，用户手指按下"),
      const LabelText("   - pointerEvent.pointer，手指id"),
      const LabelText("   - pointerEvent.localPosition，事件坐标，该坐标位置位于当前Listener组件内"),
      const LabelText("   - pointerEvent.position，事件坐标，该坐标位于整个屏幕内"),
      const LabelText("   - pointerEvent.localDelta，事件坐标相对于上个事件的差值"),
      const LabelText("   - pointerEvent.delta，事件坐标相对于上个事件的差值"),
      const LabelText("- onPointerMove，用户手指移动"),
      const LabelText("- onPointerUp，用户手指抬起"),
      const LabelText("- onPointerCancel，事件被拦截、页面销毁等事件导致本次触摸流程（按下到抬起）被取消"),
      const NoticeText("- 其它属性主要是触摸板相关的，用于PC端开发，与移动端没有太大关系"),
      const NoticeText("- 在ListView中使用时，多点触摸会被拦截，而且即使修改ListView配置"
          "为不滚动也会因为异步导致部分事件被拦截，这在同时按下多个手指时会发生。。。"),
    ];
  }
}

class _Example extends StatelessWidget {
  final GlobalKey<PageWithTitleState> pageKey;

  const _Example(this.pageKey);

  static final pointersColor = [
    Colors.blue,
    Colors.green,
    Colors.red,
    Colors.deepOrange,
    Colors.brown,
    Colors.amber,
    Colors.greenAccent,
    Colors.black,
    Colors.deepPurple,
    Colors.pinkAccent,
  ];

  static const pointRadius = 24;
  static final LinkedHashMap<int, Offset> pointersPosition = LinkedHashMap();

  @override
  Widget build(BuildContext context) {
    return StatefulBuilder(
      builder: (context, setState) {
        List<Widget> pointerWidgets = [];
        for (final (index, position) in pointersPosition.values.indexed) {
          pointerWidgets.add(Positioned(
            left: position.dx - pointRadius,
            top: position.dy - pointRadius,
            width: pointRadius * 2,
            height: pointRadius * 2,
            child: DecoratedBox(
              decoration: BoxDecoration(
                  color: pointersColor[index], shape: BoxShape.circle),
            ),
          ));
        }
        return Listener(

          onPointerDown: (pointerDownEvent) {
            pageKey.currentState?.physics =
                const NeverScrollableScrollPhysics();
            setState(() {
              pointersPosition[pointerDownEvent.pointer] =
                  pointerDownEvent.localPosition;
            });
          },
          onPointerMove: (pointerMoveEvent) {
            setState(() => pointersPosition[pointerMoveEvent.pointer] =
                pointerMoveEvent.localPosition);
          },
          onPointerUp: (pointerUpEvent) {
            setState(() {
              pointersPosition.remove(pointerUpEvent.pointer);
              if (pointersPosition.isEmpty) {
                pageKey.currentState?.physics =
                    const AlwaysScrollableScrollPhysics();
              }
            });
          },
          onPointerCancel: (pointerCancelEvent) {
            setState(() {
              pointersPosition.remove(pointerCancelEvent.pointer);
              if (pointersPosition.isEmpty) {
                pageKey.currentState?.physics =
                    const AlwaysScrollableScrollPhysics();
              }
            });
          },
          child: AspectRatio(
            aspectRatio: 1,
            child: DecoratedBox(
              decoration: BoxDecoration(
                color: Theme.of(context).colorScheme.surfaceContainer,
                borderRadius: M3.connerRadiusMedium,
              ),
              child: Stack(
                children: pointerWidgets,
              ),
            ),
          ),
        );
      },
    );
  }
}
